﻿using Inaction.Core;
using Inaction.Mapping;
using Inaction.ServiceContract;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace Inaction.Business
{
    public partial class Entity<T>
    {
        #region BusinessRules
        static Dictionary<IProperty, List<Func<T, System.Data.IDbTransaction, string>>> PropertyRules = new Dictionary<IProperty, List<Func<T, System.Data.IDbTransaction, string>>>();

        static List<Func<T, System.Data.IDbTransaction, string>> EntityRules = new List<Func<T, System.Data.IDbTransaction, string>>();

        protected static void AddRules(Func<T, System.Data.IDbTransaction, string> func, IProperty property = null)
        {
            List<Func<T, System.Data.IDbTransaction, string>> rules = null;
            if (property != null)
            {
                if (PropertyRules.ContainsKey(property))
                {
                    rules = PropertyRules[property];
                }
                else
                {
                    rules = new List<Func<T, System.Data.IDbTransaction, string>>();
                    PropertyRules.Add(property, rules);
                }
                rules.Add(func);
            }
            else
            {
                EntityRules.Add(func);
            }
        }
        #endregion

        static Entity()
        {
            AddRules((x, trans) =>
            {
                if (trans == null) return string.Empty;
                var classInfo = ClassInfo.LoadInfo(typeof(T));
                if (classInfo.Table.UniqueKeys.Count == 0) return string.Empty;
                if (!x.IsDeleted)
                {
                    var sqls = SqlStatement.GetUniqueStatement<T>((T)x);
                    foreach (var s in sqls)
                    {
                        using (var command = DbProvider.CreateCommand(trans, s))
                        {
                            var count = (int)command.ExecuteScalar();
                            if (count > 0)
                            {
                                throw new Core.UniqueException(s.Name, x.PrimaryKey.Value, x.GetType());
                            }
                        }
                    }
                }
                return string.Empty;
            });

            AddRules((x, trans) =>
            {
                if (trans == null) return string.Empty;

                if (x.IsDeleted)
                {
                    var error= string.Empty;
                    x.CheckExistsForeignKeyChildrenData(ref error, trans);
                    return error;
                }
                return string.Empty;
            });
        }
        protected override void SetProperty<P>(Property<P> property, ref P field, P newValue)
        {
            if (!CanSetProperty(property.Name)) return;
            base.SetProperty<P>(property, ref field, newValue);
        }
    }
}